package cn.lx.es.query.search.service.impl;

import cn.lx.es.query.annotation.*;
import cn.lx.es.query.processor.SearchAnnotationProcessor;
import cn.lx.es.query.search.entity.PageList;
import cn.lx.es.query.search.entity.PageSortHighLight;
import cn.lx.es.query.search.entity.SearchParam;
import cn.lx.es.query.search.service.ElasticsearchTemplate;
import cn.lx.es.query.search.service.EsSearchService;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.*;

/**
 * @ClassName EsSearchServiceImpl
 * @Description: ES搜索服务类
 * @Author: 落雪
 * @CreateDate: 2025/7/3 08:32
 * @UpdateUser: 落雪
 * @UpdateDate: 2025/7/3 08:32
 * @UpdateRemark:
 * @Version: 1.0
 */
public class EsSearchServiceImpl<T extends PageSortHighLight> implements EsSearchService<T> {

    @Autowired
    private ElasticsearchTemplate<T, String> elasticsearchTemplate;

    private final List<SearchAnnotationProcessor> processors;
    
    // 处理器映射表
    private Map<Class<? extends Annotation>, SearchAnnotationProcessor> processorMap;

    /**
     * 构造函数，接收处理器列表
     * @param processors 搜索注解处理器列表
     */
    public EsSearchServiceImpl(List<SearchAnnotationProcessor> processors) {
        this.processors = processors;
        initProcessorMap();
    }

    @Override
    public PageList<T> search(SearchParam<T> param, Class<T> clazz) {
        try {
            // 构建查询条件
            BoolQueryBuilder boolQueryBuilder = buildBoolQuery(param.getT(), clazz);
            
            // 使用ElasticsearchTemplate进行搜索
            return elasticsearchTemplate.search(boolQueryBuilder, param.getT(), clazz);
            
        } catch (Exception e) {
            throw new RuntimeException("ES搜索失败", e);
        }
    }

    @Override
    public PageList<T> search(SearchParam<T> param, Class<T> clazz, String... indices) {
        try {
            // 构建查询条件
            BoolQueryBuilder boolQueryBuilder = buildBoolQuery(param.getT(), clazz);
            
            // 使用ElasticsearchTemplate进行跨索引搜索
            return elasticsearchTemplate.search(boolQueryBuilder, param.getT(), clazz, indices);
            
        } catch (Exception e) {
            throw new RuntimeException("ES跨索引搜索失败", e);
        }
    }

    /**
     * 初始化处理器映射表
     */
    private void initProcessorMap() {
        processorMap = new HashMap<>();
        for (SearchAnnotationProcessor processor : processors) {
            processorMap.put(processor.getAnnotationType(), processor);
        }
    }

    /**
     * 构建布尔查询
     */
    private BoolQueryBuilder buildBoolQuery(T searchParam, Class<T> clazz) {
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        
        // 获取所有字段
        Field[] fields = clazz.getDeclaredFields();
        
        for (Field field : fields) {
            field.setAccessible(true);
            
            try {
                Object value = field.get(searchParam);
                if (value == null) {
                    continue;
                }
                
                // 获取字段上的所有注解
                Annotation[] annotations = field.getAnnotations();
                for (Annotation annotation : annotations) {
                    SearchAnnotationProcessor processor = processorMap.get(annotation.annotationType());
                    if (processor != null) {
                        processor.process(annotation, field, value, boolQueryBuilder);
                    }
                }
                
            } catch (IllegalAccessException e) {
                // 忽略无法访问的字段
            }
        }
        
        return boolQueryBuilder;
    }
}



